package br.com.cfccultura.admin.control.actions.aluno;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.springframework.stereotype.Component;

import br.com.cfccultura.admin.control.actions.DefaultAction;
import br.com.cfccultura.admin.control.forms.aluno.MatricularForm;
import br.com.cfccultura.admin.model.enums.CategoriaCnh;
import br.com.cfccultura.admin.model.enums.DiaSemana;
import br.com.cfccultura.admin.model.enums.FormaPagamento;
import br.com.cfccultura.admin.model.enums.Sexo;
import br.com.cfccultura.admin.model.enums.SimNao;
import br.com.cfccultura.admin.model.enums.SituacaoConta;
import br.com.cfccultura.admin.model.enums.TipoCurso;
import br.com.cfccultura.admin.model.enums.UF;
import br.com.cfccultura.admin.model.vo.AgendamentoProva;
import br.com.cfccultura.admin.model.vo.Aluno;
import br.com.cfccultura.admin.model.vo.Banco;
import br.com.cfccultura.admin.model.vo.CalendarioDia;
import br.com.cfccultura.admin.model.vo.ComputadorProva;
import br.com.cfccultura.admin.model.vo.ContaReceber;
import br.com.cfccultura.admin.model.vo.Curso;
import br.com.cfccultura.admin.model.vo.Matricula;
import br.com.cfccultura.admin.model.vo.OrdemServico;
import br.com.cfccultura.admin.model.vo.OrdemServicoEspecie;
import br.com.cfccultura.admin.model.vo.OrdemServicoItem;
import br.com.cfccultura.admin.model.vo.ServicoAluno;
import br.com.cfccultura.admin.model.vo.Turma;
import br.com.cfccultura.admin.view.report.ReportManager.Type;

@Component("/matricularAluno")
public class MatricularAction extends DefaultAction {
	
	private static final Logger logger = Logger.getLogger(MatricularAction.class);
	
	public ActionForward iniciar(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {		

		request.getSession().setAttribute("carrinhoServicos", new ArrayList<ServicoAluno>());
		
		return mapping.findForward("body");
	}
	
	public ActionForward verificaDataProva(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {		
		
		MatricularForm matricularForm = (MatricularForm) form;
		Date dataProva = getDateFormat().parse(matricularForm.getDataProva());
		
		CalendarioDia dia = getCalendarioDAO().consultar(dataProva);
		
		Object[] params = {true, "", "", ""};
		
		if(dia == null) {
			params[0] = false;
			params[1] = "Dia " + getDateFormat().format(dataProva) + " não previsto no Calendário do Sistema.\nFavor informar ao Administrador!";			
		} else if(dia.getFeriado().equals(SimNao.SIM)) {
			params[0] = false;
			params[1] = "Dia " + getDateFormat().format(dia.getData()) + " é Feriado: " + dia.getDescricao();
		} else if(dia.getDiaSemana().equals(DiaSemana.DOMINGO)) {
			params[0] = false;
			params[1] = "Não é permitido marcar provas no Domingo. Favor selecionar uma nova data!";
		}
		
		if(((Boolean)params[0]) != false) {
			List<AgendamentoProva> marcados = getAgendamentoProvaDAO().consultaDisponibilidade(dataProva);
			List<ComputadorProva> computadores = getComputadorProvaDAO().consultar(new ComputadorProva());
			
			int qtdeComputadores = 0;
			for(ComputadorProva computador : computadores) {
				if(computador.getDisponivel().equals(SimNao.SIM))
					qtdeComputadores++;
			}
			
			Calendar c = Calendar.getInstance();
			if(getDateFormat().format(dataProva).equals(getDateFormat().format(new Date()))) {
				c.setTime(new Date());
				if(c.get(Calendar.MINUTE) <= 30) {
					c.set(Calendar.MINUTE, 30);
				} else if(c.get(Calendar.MINUTE) > 30) {
					c.set(Calendar.MINUTE, 0);
					c.add(Calendar.HOUR_OF_DAY, 1);
				}					
			} else {
				c.setTime(dataProva);
				c.set(Calendar.HOUR_OF_DAY, 8);
				c.add(Calendar.MINUTE, 0);
			}
			c.set(Calendar.SECOND, 0);
			c.set(Calendar.MILLISECOND, 0);

			List<String> horarios = new ArrayList<String>();
			while(true) {
				String hora = getSimpleHourFormat().format(c.getTime());
				horarios.add(hora);
				if(hora.equals("18:00") || hora.equals("18:10") || hora.equals("18:20") || hora.equals("18:30") || hora.equals("18:40") || hora.equals("18:50"))
					break;
				c.add(Calendar.MINUTE, 40);
			}			
			
			List<String> remover = new ArrayList<String>();
			for(String horario : horarios) {
				int qtdeMarcadosHorario = 0;
				
				for(AgendamentoProva marcado : marcados) {
					String horaMarcada = getSimpleHourFormat().format(marcado.getDataHora());				
					if(horario.equals(horaMarcada)) {
						qtdeMarcadosHorario++;
					}
				}
				
				if(qtdeMarcadosHorario >= qtdeComputadores) {
					remover.add(horario);
				}
			}
			
			for(String remove : remover) {
				horarios.remove(remove);
			}
			
			params[1] = horarios;
		}
		
		printJsonObjectToStream(params, response);		

		return null;
	}
	
	public ActionForward manterDadosAluno(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {		
		
		MatricularForm matricularForm = (MatricularForm) form;
		Aluno vo = new Aluno();
		
		if(matricularForm.getCodigo() != null) {
			vo.setCodigo(matricularForm.getCodigo());
		}
		
		vo.setCpf(matricularForm.getCpf());
		vo.setNome(matricularForm.getNome());
		vo.setDataNascimento(getDateFormat().parse(matricularForm.getDataNascimento()));
		vo.setRg(matricularForm.getRg());
		vo.setOrgaoExpeditor(matricularForm.getOrgaoExpeditor());
		vo.setSexo(Sexo.valueOf(matricularForm.getSexo()));
		vo.setDeficienteFisico(SimNao.valueOf(matricularForm.getDeficiente()));
		
		if(matricularForm.getPgu() != null && !matricularForm.getPgu().equals(""))
			vo.setPgu(matricularForm.getPgu());
		if(matricularForm.getCategoria() != null && !matricularForm.getCategoria().equals(""))
			vo.setCategoriaCnh(CategoriaCnh.valueOf(matricularForm.getCategoria()));
		if(matricularForm.getDataPrimeiraHabilitacao() != null && !matricularForm.getDataPrimeiraHabilitacao().equals(""))
			vo.setDataPrimeiraHabilitacao(getDateFormat().parse(matricularForm.getDataPrimeiraHabilitacao()));
		
		vo.setCep(matricularForm.getCep());
		vo.setEndereco(matricularForm.getEndereco());
		vo.setNumero(matricularForm.getNumero());
		vo.setComplemento(matricularForm.getComplemento());
		vo.setBairro(matricularForm.getBairro());
		vo.setCidade(matricularForm.getCidade());
		vo.setUf(UF.valueOf(matricularForm.getUf()));
		
		vo.setTelefoneResidencia(matricularForm.getTelefone());
		vo.setTelefoneCelular(matricularForm.getCelular());
		vo.setTelefoneComercial(matricularForm.getComercial());
		vo.setEmail(matricularForm.getEmail());
		
		vo.setFuncionarioCadastro(getUsuario(request));
		
		if(vo.getCodigo() == null || vo.getCodigo() == 0) { //incluir
			getAlunoDAO().incluir(vo);
		} else { //alterar
			getAlunoDAO().alterar(vo);
		}
		
		printJsonObjectToStream(new Object[] {vo.getCodigo()}, response);
		
		return null;
	}
		
	public ActionForward incluirCurso(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {		
		
		MatricularForm matricularForm = (MatricularForm) form;
		Object[] params = {true, ""};
		
		Turma turma = null;
		if(matricularForm.getTurma() != null && matricularForm.getTurma() > 0) {
			turma = getTurmaDAO().consultar(matricularForm.getTurma());
			for(Matricula matricula : turma.getMatriculas()) {
				if(matricula.getAluno().getCpf().equals(matricularForm.getCpf())) {
					params = new Object[]{false, "Este aluno já está cadastrado nessa Turma!"};
					printJsonObjectToStream(params, response);
					return null;
				}				
			}
		}
		
		Curso cursoSelecionado = getCursoDAO().consultar(matricularForm.getCurso());
		TipoCurso tipoCurso = TipoCurso.setValue(matricularForm.getTipoCurso());
		
		
		
		//Remove curso adicionado anteriormente
		List<ServicoAluno> servicos = (List<ServicoAluno>) request.getSession().getAttribute("carrinhoServicos");
		ServicoAluno[] remover = {null, null};		
		int i=0;
		for(ServicoAluno s : servicos) {
			if(s.getCurso() != null) 
				remover[i] = s;
			i++;
		}
		for(ServicoAluno sa : remover) {
			if(sa != null)
				servicos.remove(sa);
		}		
		
		
		if(tipoCurso.equals(TipoCurso.PRESENCIAL)) {
			ServicoAluno curso = new ServicoAluno();
			curso.setCurso(cursoSelecionado);
			curso.setTipoCurso(tipoCurso);
			curso.setQtde(1);
			
			servicos.add(curso);
		}
		
		if(cursoSelecionado.getCodigo().equals(3)) { //Renovação de CNH
			ServicoAluno prova = new ServicoAluno();
			prova.setCurso(cursoSelecionado);
			prova.setProva(true);
			prova.setQtde(1);
			servicos.add(prova);
		}		
		
		printJsonObjectToStream(params, response);
		
		return null;
	}
	
	public ActionForward matricular(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {		
		
		MatricularForm matricularForm = (MatricularForm) form;
		
		Aluno aluno = getAlunoDAO().consultar(matricularForm.getCodigo());
		Curso curso = getCursoDAO().consultar(matricularForm.getCurso());
		TipoCurso tipoCurso = TipoCurso.setValue(matricularForm.getTipoCurso());
		
		Turma turma = null;
		if(matricularForm.getTurma() > 0)
			turma = getTurmaDAO().consultar(matricularForm.getTurma());
		FormaPagamento formaPagamento = FormaPagamento.setValue(matricularForm.getFormaPagamento());
	
		Matricula matricula = null;
		if(tipoCurso.equals(TipoCurso.PRESENCIAL)) { //Se PRESENCIAL, realiza Matricula
			matricula = new Matricula();
			matricula.setTurma(turma);
			matricula.setAluno(aluno);
			matricula.setUsuarioSistema(getUsuario(request));
			getTurmaDAO().matricular(matricula);
		}
		
		AgendamentoProva prova = null;
		if(curso.getCodigo().equals(3)) { //Se curso Renovação, agenda prova
			
			Integer hora = new Integer(matricularForm.getHoraProva().substring(0, 2));
			Integer minuto = new Integer(matricularForm.getHoraProva().substring(3, 5));
			Calendar c = Calendar.getInstance();
			c.setTime(getDateFormat().parse(matricularForm.getDataProva()));
			c.set(Calendar.HOUR_OF_DAY, hora);
			c.set(Calendar.MINUTE, minuto);
			c.set(Calendar.SECOND, 0);
			c.set(Calendar.MILLISECOND, 0);
			
			Date dataProva = c.getTime();
			
			List<AgendamentoProva> marcados = getAgendamentoProvaDAO().consultaDisponibilidade(dataProva);
			List<ComputadorProva> computadores = getComputadorProvaDAO().consultar(new ComputadorProva());
			
			ComputadorProva computadorProva = null;
			
			for(ComputadorProva computador : computadores) {
				if(computador.getDisponivel().equals(SimNao.SIM)) {
					boolean disponivel = true;
					for(AgendamentoProva marcado : marcados) {
						if(marcado.getComputador().getCodigo().equals(computador.getCodigo())) {
							disponivel = false;
						}
					}
					if(disponivel) {
						computadorProva = computador;
						break;
					}
				}					
			}			
			
			prova = new AgendamentoProva();
			prova.setAluno(aluno);
			prova.setCurso(curso);
			prova.setComputador(computadorProva);
			prova.setDataHora(dataProva);
			prova.setUsuarioSistema(getUsuario(request));
			getAgendamentoProvaDAO().incluir(prova);
		}
		
		OrdemServico ordemServico = new OrdemServico();
		ordemServico.setAluno(aluno);
		ordemServico.setCadastro(new Date());
		ordemServico.setUsuarioSistema(getUsuario(request));
		
		if(matricula != null) {
			matricula.setOrdemServico(ordemServico);
			OrdemServicoItem item = new OrdemServicoItem();
			item.setMatricula(matricula);
			item.setQtde(1);
			item.setTipoCurso(tipoCurso);
			item.setValorVenda(curso.getValorVenda());
			item.setValorCusto(curso.getValorCusto());
			item.setUsuarioSistema(getUsuario(request));
			ordemServico.getItems().add(item);
		}
		
		if(prova != null) {
			OrdemServicoItem item = new OrdemServicoItem();
			item.setAgendamentoProva(prova);
			item.setQtde(1);
			item.setTipoCurso(tipoCurso);
			item.setValorVenda(curso.getValorProvaVenda());
			item.setValorCusto(curso.getValorProvaCusto());
			item.setUsuarioSistema(getUsuario(request));
			ordemServico.getItems().add(item);
		}
		
		List<ServicoAluno> servicos = (List<ServicoAluno>) request.getSession().getAttribute("carrinhoServicos");
		for(ServicoAluno servico : servicos) {
			if(servico.getServico() != null){
				OrdemServicoItem item = new OrdemServicoItem();
				item.setServico(servico.getServico());
				item.setQtde(servico.getQtde());
				item.setUsuarioSistema(getUsuario(request));
				item.setValorCusto(servico.getServico().getValorCusto());
				item.setValorVenda(servico.getServico().getValorVenda());
				ordemServico.getItems().add(item);
			}
		}
		
		OrdemServicoEspecie especie = new OrdemServicoEspecie();
		especie.setFormaPagamento(formaPagamento);
		especie.setOrdemServico(ordemServico);
		especie.setValor(getDecimalFormat().parse(matricularForm.getValorPagamento()).doubleValue());
		if(formaPagamento.equals(FormaPagamento.CHEQUE)) {
			especie.setBanco(new Banco(matricularForm.getBanco()));
			especie.setAgencia(matricularForm.getAgencia());
			especie.setConta(matricularForm.getConta());
			especie.setCheque(matricularForm.getCheque());
			especie.setDataCheque(getDateFormat().parse(matricularForm.getDataCheque()));
		}
		especie.setUsuarioSistema(getUsuario(request));		
		ordemServico.getEspecies().add(especie);
		
		getOrdemServicoDAO().incluir(ordemServico);
		
		ContaReceber conta = new ContaReceber();
		conta.setOrdemServicoEspecie(especie);
		
		Double valorPago = 0D;
		Double saldo = 0D;
		
		if(matricula != null) {
			conta.setDescricao(matricula.getTurma().getCurso().getNome() + " (curso)");
		} else if(prova != null) {
			conta.setDescricao(prova.getCurso().getNome() + " (prova)");
		}		
		
		if(especie.getFormaPagamento().equals(FormaPagamento.DINHEIRO)) {
			conta.setVencimento(new Date()); 
			conta.setPagamento(new Date());
			valorPago = getDecimalFormat().parse(matricularForm.getValorPagamento()).doubleValue();
			if(valorPago < ordemServico.getTotal()) {
				saldo = ordemServico.getTotal() - valorPago;
				conta.setSituacao(SituacaoConta.PENDENTE_ALUNO);
			} else {
				conta.setSituacao(SituacaoConta.PAGO);
			}
			conta.setValorPagamento(valorPago);
		} else if(especie.getFormaPagamento().equals(FormaPagamento.CHEQUE)) {
			conta.setVencimento(getDateFormat().parse(matricularForm.getDataCheque()));
			conta.setSituacao(SituacaoConta.PENDENTE);
			conta.setValorPagamento(getDecimalFormat().parse(matricularForm.getValorPagamento()).doubleValue());
			valorPago = getDecimalFormat().parse(matricularForm.getValorPagamento()).doubleValue();
		} else if(especie.getFormaPagamento().equals(FormaPagamento.ABERTO)) {
			if(turma != null)
				conta.setVencimento(turma.getTermino());
			else if(prova != null)
				conta.setVencimento(prova.getDataHora());
			saldo = ordemServico.getTotal();
			conta.setSituacao(SituacaoConta.PENDENTE_ALUNO);
			conta.setValorPagamento(0D);
		}
		conta.setUsuarioSistema(getUsuario(request));
		getFluxoCaixaDAO().incluir(conta);
		
		HashMap<String, Object> params = new HashMap<String, Object>();
		params.put("aluno", aluno);
		params.put("matricula", matricula);
		params.put("prova", prova);
		params.put("valorPago", valorPago);
		params.put("saldo", saldo);
		
		request.getSession().setAttribute("reportType", Type.COMPROVANTE_MATRICULA);
		request.getSession().setAttribute("jasperParams", params);
		request.getSession().setAttribute("jasperDs", ordemServico.getItems());
		
		return null;
	}

}
